home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 3: CDPD 3
/
Almathera Ten on Ten - Disc 3: CDPD3.iso
/
fish
/
751-760
/
758
/
mine
/
txt
/
mine.mod
< prev
Wrap
Text File
|
1995-03-18
|
57KB
|
1,789 lines
(************************************************************************************
:Program. Mine
:Contents. neue Implementation eines alten Computer-Spiels
:Remark. benötigt KICK 2.00^
:Copyright. "freely distributable copyrighted software"
:Author. Thomas Ansorge
:Address. Dinkelackerring 55, W-6730 Neustadt, Deutschland, Europa
:Language. Modula-2
:Translator. M2Amiga V4.096 (deutsch)
:Imports. BeepSupport [Thomas Ansorge]
:Imports. Images [Thomas Ansorge]
:Imports. OptReqL [Thomas Ansorge]
:Imports. OptReqToolsL [Thomas Ansorge]
:Imports. ReqSupport [Thomas Ansorge]
:Support. reqtools.library (Nico François) falls vorhanden, sonst
:Support. req.library (Colin Fox, Bruce Dawson) falls vorhanden
:Support. viele Tips von Michi
:Support. Fridtjof half debuggen
:Version. 1.6 vom 21.09.1992
:History. 1.0 vom 08.08.1992: es läuft.
:History. 1.1 vom 23.08.1992:
:History. - mit 0-Automatik
:History. - ab spielfeldMax >= 8: Anzeige Anzahl Fahnen
:History. 1.2 vom 11.09.1992:
:History. - "Zeiger ist NIL"-Bug unter KICK 39.x.
:History. - Nil-Chk abgestellt (funktioniert oft, hier?)
:History. 1.3 vom 11.09.1992: Sicherheitsabfrage PropInfo beim Slider
:History. 1.4 vom 14.09.1992:
:History. - Gadget-Abfrage sicherer
:History. - Ruhmeshalle einfach per Mausklick verlaßbar
:History. - Nil-Chk wieder drin.
:History. - closeWindow beendet jetzt stets das Spiel, die
:History. Ruhmeshalle wird per Klick ins Fenster verlassen
:History. - Anzahl Minen in 2 verschiedenen Farben
:History. - BANG-Requester raus
:History. - Abfrage "IF gadgetPtr # NIL" im ersten Fenster bei der Abfrage
:History. der Gadgets nach "IF gadgetUp IN flags". Ist das der Bug unter
:History. OS 39.x (beta)?
:History. - Mausklick beendet Minen-Fenster, falls kein Str-Requester
:History. 1.5 vom 17.09.1992:
:History. - Bug in der Programmierung von GadTools behoben (es war eine
:History. fehlende PropInfo-Struktur)
:History. 1.6 vom 21.09.1992:
:History. - Abfrage der Msg-Ports jetzt gemäß RKM: Libraries
:History. - explizite Liste der benötigten Lib.-Mindestversionen
:History. - RefreshWindow jetzt in jedem Fenster
************************************************************************************)
(*$ DEFINE Deutsch := TRUE *)
MODULE Mine;
FROM Arts IMPORT Assert;
FROM ASCII IMPORT nul;
FROM BeepSupport IMPORT Beep, infoPri, Sound;
FROM Conversions IMPORT ValToStr;
FROM DiskFontL IMPORT diskfontVersion, OpenDiskFont;
FROM DosD IMPORT Date, DatePtr;
FROM DosL IMPORT dosVersion, DateStamp;
FROM ExecL IMPORT execVersion, GetMsg, ReplyMsg, WaitPort;
FROM FileSystem IMPORT Close, File, Lookup, ReadByteBlock, Response, WriteByteBlock;
FROM GadToolsD IMPORT buttonIDCMP, buttonKind, GtTags, NewGadget, NewGadgetFlags,
NewGadgetFlagSet, sliderIDCMP, sliderKind;
FROM GadToolsL IMPORT CreateContext, CreateGadgetA, DrawBevelBoxA, FreeGadgets,
FreeVisualInfo, gadtoolsVersion, GetVisualInfoA, GTBeginRefresh, GTEndRefresh,
GTGetIMsg, GTRefreshWindow, GTReplyIMsg;
FROM GraphicsD IMPORT FontFlagSet, FontStyleSet, jam2, TextAttr, TextFontPtr;
FROM GraphicsL IMPORT graphicsVersion, CloseFont;
IMPORT Images;
FROM InputEvent IMPORT Qualifiers, QualifierSet;
FROM IntuitionD IMPORT GadgetPtr, GaTags, IDCMPFlags, IDCMPFlagSet, Image,
IntuiMessage, IntuiMessagePtr, IntuiText, Screen, ScreenPtr, WaTags, Window,
WindowFlags, WindowFlagSet, WindowPtr;
FROM IntuitionL IMPORT AddGList, BeginRefresh, CloseWindow, DrawImage, EndRefresh,
intuitionVersion, LockPubScreen, ModifyIDCMP, OpenWindowTagList, PrintIText,
RefreshGadgets, RemoveGList, UnlockPubScreen;
FROM OptReqL IMPORT reqBase;
FROM OptReqToolsL IMPORT reqtoolsBase;
IMPORT R;
FROM RandomNumber IMPORT PutSeed, RND;
FROM RequesterSupport IMPORT noError, ReqLib, TextRequest, StringRequest;
FROM String IMPORT Concat, ConcatChar, Copy, Insert;
FROM SYSTEM IMPORT ADDRESS, ADR, ASSEMBLE, CAST, TAG;
FROM UtilityD IMPORT tagEnd;
(* ------------------------------------------------------------------------------- *)
(* die Farbverteilung auf der Standard-Workbench *)
CONST grau = 0;
schwarz = 1;
weiss = 2;
blau = 3;
CONST mineStr = "Mine";
CONST sliderGadID = 1;
weiterGadID = 2;
infoGadID = 3;
ruhmGadID = 4;
(* TAG-Listen *)
CONST maxTags = 9;
(* der Font *)
CONST fontHoehe = 8;
fontName = "topaz.font";
(*$ IF Deutsch *)
CONST info = "Infos und Hilfe";
kick20 = "Mine benötigt KICK 2.00^!";
openWindowError = "konnte Fenster nicht öffnen!";
ruhmeshalleFensterName = "Mine Ruhmeshalle für n = ";
ruhmeshalleGadgetName = "Ruhmeshalle ansehen";
seitenlaenge = "Seitenlänge:";
stringReqTitle = "Mine: Ihren Namen bitte:";
userPortError = "leider kein IDCMP im Fenster!";
weiter = "weiter";
zeitS = "Zeit: ";
(*$ ELSE *)
CONST info = "infos and help";
kick20 = "Mine needs KICK 2.00^!";
openWindowError = "could not open window!";
ruhmeshalleFensterName = "Mine Highscores for n = ";
ruhmeshalleGadgetName = "show Highscores";
seitenlaenge = "field size :";
stringReqTitle = "Mine: Please enter your name:";
userPortError = "Could not get IDCMP!";
weiter = "continue";
zeitS = "Time: ";
(*$ ENDIF *)
(* Das Spielfeld *)
CONST boxX = 24;
boxY = 12;
fahne = -20; (* wird auf Wert addiert *)
horoffset = 1;
mine = -1;
nummer = -3;
randBreite = 2;
(* Das quadratische Spielfeld *)
TYPE Spielfeld = ARRAY [1..77], [1..77] OF SHORTINT;
TYPE Zeit = RECORD
ticks : [0..49]; (* 50 Ticks pro Sekunde von Intuition *)
minuten : LONGINT;
sekunden : LONGINT;
zeitStr : ARRAY [0..11] OF CHAR;
hilfeStr : ARRAY [0..2] OF CHAR;
zeitIText: IntuiText;
END (* RECORD Zeit *);
(* Die Ruhmeshalle *)
CONST ruhmeshalleName = "Mine-Highscores_";
TYPE StringRuhm = ARRAY [0..26] OF CHAR; (* der komplette String mit allem drin! *)
RuhmeshalleEintrag = RECORD
anzM: LONGINT;
zeit: RECORD
min,
sec: LONGINT;
END (* RECORD Zeit *);
name: StringRuhm;
END (* RECORD *);
Ruhmeshalle = ARRAY [1..10] OF RuhmeshalleEintrag;
VAR anzFahnen : LONGINT;
anzMinen : LONGINT;
anzNummer : LONGINT;
bombeImage : Image;
clickedImage : Image;
clickmeImage : Image;
code : CARDINAL;
contextPtr : GadgetPtr;
date : Date;
eintrag : RuhmeshalleEintrag;
ende : BOOLEAN;
err : BOOLEAN;
explosionImage : Image;
fahneImage : Image;
fahneORImage : Image;
flags : IDCMPFlagSet;
fontAttr : TextAttr;
fontPtr : TextFontPtr;
gadgetPtr : GadgetPtr;
gList : GadgetPtr;
i : INTEGER;
innerWidth : LONGINT;
innerHeight : LONGINT;
intuiText : IntuiText;
j : INTEGER;
mausX, mausY : INTEGER;
nachricht : IntuiMessagePtr;
newGadget : NewGadget;
pos : LONGINT; (* Platz in der Ruhmeshalle *)
qualifiers : QualifierSet;
reqLib : ReqLib;
ruhmeshalle : Ruhmeshalle;
ruhmeshalleEintr: RuhmeshalleEintrag;
screenPtr : ScreenPtr;
sliderZahlPos : INTEGER;
spielfeld : Spielfeld;
spielfeldMax : LONGINT;
spielFeldMax : LONGINT;
string2 : ARRAY [0..2] OF CHAR;
string30 : ARRAY [0..30] OF CHAR;
string80 : ARRAY [0..80] OF CHAR;
tagList : ARRAY [1..2 * maxTags] OF LONGINT;
visualInfo : ADDRESS;
windowPtr : WindowPtr;
windowPtr2 : WindowPtr;
zeit : Zeit;
(* ------------------------------------------------------------------------------- *)
(* Die Prozeduren etc. sind alphabetisch sortiert, daher sind evt. FORWARDs nötig. *)
PROCEDURE Ziffer (ziffer: SHORTINT): CHAR; FORWARD;
(* ------------------------------------------------------------------------------- *)
PROCEDURE AnzMinen (spielfeldMax: LONGINT): LONGINT;
BEGIN (* Funktion AnzMinen *)
RETURN (spielfeldMax * spielfeldMax) DIV 6;
END AnzMinen (* Funktion *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE DrawClickedImage (VAR windowPtr: WindowPtr;
VAR spielfeld: Spielfeld;
spielfeldMax : INTEGER;
i, j : INTEGER;
VAR anzNummer: LONGINT);
(* spielfeld [i, j] # mine! *)
(* zeichnet das Clicked-Image, schreibt die Anzahl an Minen hinein, falls 0: *)
(* ruft rekursiv sich selbst auf, bis keine 0 mehr da *)
(* i: Zeile, j: Spalte *)
VAR
intuiText: IntuiText;
string2 : ARRAY [0..2] OF CHAR;
(* ---------------------------------------------------------------------------- *)
PROCEDURE Farbe (zeile, spalte, anzMinen, max: INTEGER): SHORTCARD;
(* ------------------------------------------------------------------------- *)
PROCEDURE Nachbarn (zeile, spalte, max: INTEGER): INTEGER;
(* macht Gebrauch davon, daß das Spielfeld quadratisch ist *)
BEGIN (* Funktion Nachbarn *)
IF ((zeile = 1) AND (spalte = 1)) OR ((zeile = max) AND (spalte = max)) OR
((zeile = 1) AND (spalte = max)) OR ((zeile = max) AND (spalte = 1)) THEN
RETURN 3;
ELSE (* IF (zeile = spalte) *)
IF (zeile = 1) OR (spalte = 1) OR (zeile = max) OR (spalte = max) THEN
RETURN 5; (* Rand, aber keine Ecke *)
ELSE (* IF (zeile = 1 *)
RETURN 8; (* mittendrin *)
END (* IF (zeile = 1 *);
END (* IF (zeile = spalte *);
END Nachbarn (* Funktion *);
(* ------------------------------------------------------------------------- *)
BEGIN (* Funktion Farbe *)
IF anzMinen = 0 THEN
RETURN grau;
END (* IF anzMinen *);
IF Nachbarn (zeile, spalte, max) > (2 * anzMinen) THEN
RETURN schwarz;
ELSE (* IF (Nachbarn *)
RETURN blau;
END (* IF (Nachbarn *);
END Farbe (* Funktion *);
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur DrawClickedImage *)
DrawImage (windowPtr^.rPort, ADR (clickedImage),
2 * randBreite + (j - 1) * clickedImage.width + horoffset * (j - 1),
randBreite + (i - 1) * clickedImage.height);
intuiText.frontPen := Farbe (i, j, spielfeld [i, j], spielfeldMax);
IF intuiText.frontPen # grau THEN
WITH intuiText DO
(* frontPen: s. o. *)
backPen := grau;
leftEdge := 8;
topEdge := 2;
drawMode := jam2;
iText := ADR (string2);
iTextFont := ADR (fontAttr);
nextText := NIL;
END (* WITH intuiText *);
string2 [0] := Ziffer (spielfeld [i, j]);
string2 [1] := nul;
PrintIText (windowPtr^.rPort, ADR (intuiText),
2 * randBreite + (j - 1) * clickedImage.width + horoffset * (j - 1),
randBreite + (i - 1) * clickedImage.height);
END (* IF intuiText.frontPen *);
(* 0 soweit vorhanden abräumen *)
IF spielfeld [i, j] = 0 THEN
spielfeld [i, j] := nummer;
INC (anzNummer);
IF i # 1 THEN
IF j # 1 THEN
IF spielfeld [i - 1, j - 1] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i - 1, j - 1,
anzNummer);
END (* IF spielfeld *);
END (* IF j *);
IF spielfeld [i - 1, j] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i - 1, j,
anzNummer);
END (* IF spielfeld *);
IF j # spielfeldMax THEN
IF spielfeld [i - 1, j + 1] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i - 1, j + 1,
anzNummer);
END (* IF spielfeld *);
END (* IF j *);
END (* IF i # 1 *);
IF j # 1 THEN
IF spielfeld [i, j - 1] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i, j - 1,
anzNummer);
END (* IF spielfeld *);
END (* IF j *);
IF j # spielfeldMax THEN
IF spielfeld [i, j + 1] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i, j + 1,
anzNummer);
END (* IF spielfeld *);
END (* IF j *);
IF i # spielfeldMax THEN
IF j # 1 THEN
IF spielfeld [i + 1, j - 1] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i + 1, j - 1,
anzNummer);
END (* IF spielfeld *);
END (* IF j *);
IF spielfeld [i + 1, j] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i + 1, j,
anzNummer);
END (* IF spielfeld *);
IF j # spielfeldMax THEN
IF spielfeld [i + 1, j + 1] >= 0 THEN
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i + 1, j + 1,
anzNummer);
END (* IF spielfeld *);
END (* IF j *);
END (* IF i # spielfeldMax *);
ELSE (* IF spielfeld [i, j] *)
(* Das ist NICHT wegoptimierbar!!! Sonst dicker BUG!!! *)
spielfeld [i, j] := nummer;
INC (anzNummer);
END (* IF spielfeld [i, j] *);
END DrawClickedImage (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE Eor (z1{R.D0}, z2{R.D1}: LONGINT): LONGINT;
BEGIN (* Funktion Eor *)
ASSEMBLE (
EOR.L D1, D0
END);
RETURN z1;
END Eor (* Funktion *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE FuegeEintragEin (VAR ruhmeshalle: Ruhmeshalle;
eintrag : RuhmeshalleEintrag;
pos : LONGINT);
VAR err : BOOLEAN;
i : [1..10];
hilfe: ARRAY [0..2] OF CHAR;
str : ARRAY [0..SIZE (eintrag.name)] OF CHAR;
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur FuegeEintragEin *)
(* Platz schaffen *)
FOR i := 9 TO pos BY -1 DO
ruhmeshalle [i + 1].anzM := ruhmeshalle [i].anzM;
ruhmeshalle [i + 1].zeit.min := ruhmeshalle [i].zeit.min;
ruhmeshalle [i + 1].zeit.sec := ruhmeshalle [i].zeit.sec;
Copy (ruhmeshalle [i + 1].name, ruhmeshalle [i].name);
END (* FOR i *);
(* eintragen *)
ValToStr (eintrag.anzM, FALSE, str, 10, 3, " ", err);
ConcatChar (str, " ");
ValToStr (eintrag.zeit.min, FALSE, hilfe, 10, 2, "0", err);
Concat (str, hilfe);
ConcatChar (str, ":");
ValToStr (eintrag.zeit.sec, FALSE, hilfe, 10, 2, "0", err);
Concat (str, hilfe);
ConcatChar (str, " ");
Concat (str, eintrag.name);
WITH ruhmeshalle [pos] DO
anzM := eintrag.anzM;
zeit.min := eintrag.zeit.min;
zeit.sec := eintrag.zeit.sec;
Copy (name, str);
END (* WITH *);
END FuegeEintragEin (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE Info (windowPtr: WindowPtr);
(* zeigt via Text-Requester Infos und Hilfen zum Spiel an *)
(*$ IF Deutsch *)
CONST quitGad = "Quit";
CONST shareware = (* war mal Shareware, daher der Name *)
" Mine © 1992 by\n" +
"\n" +
" Thomas Ansorge, Dinkelackerring 55, W-6730 Neustadt/Weinstaße,\n" +
" Deutschland, Europa\n" +
"\n" +
"\n" +
"\"Mine\" besteht aus den Dateien Mine.deutsch, Mine.english, Mine.dok,\n" +
"Mine.doc und Mine-Quelltexte.lha.\n" +
"\n" +
"Mine ist \"freely distributable copyrighted software\". Sie dürfen es nur\n" +
"auf nicht-kommerzieller Basis und nur als Ganzes weiterverbreiten und\n" +
"benutzen, aber alle anderen Rechte bleiben bei mir.\n" +
"\n" +
"Die (insgesamt 73) Dateien Mine-Highscores_?? sind von Mine verwaltete\n" +
"Highscore-Listen, die zwar zu Mine gehören, aber beim Weiterkopieren\n" +
"weggelassen werden dürfen. Sie sollten allerdings dabei sein.\n" +
"\n" +
"Mit Ausnahme der Highscore-Listen (dort ist es erwünscht) darf Mine nicht\n" +
"verändert werden.\n" +
"\n" +
"Da ich für Mine kein Geld verlange, sehe ich auch nicht ein, weshalb ich\n" +
"irgendeine Verantwortung für Schäden, die durch Mine direkt oder indirekt\n" +
"verursacht werden, aufkommen soll. SIE BENUTZEN MINE AUF EIGENE GEFAHR!";
CONST sharewareTitel = "Mine:";
CONST spielregeln =
"Das Spiel Mine funktioniert nach folgenden Regeln:\n" +
"\n" +
"Sie haben ein quadratisches Spielfeld mit n * n Feldern. Zufällig über\n" +
"diese Felder verteilt liegen INTEGER (n * n / 6) Minen versteckt. Diese\n" +
"gilt es möglichst schnell zu finden. Dazu können Sie die Felder mit der\n" +
"linken Maustaste anklicken. Ist auf dem Feld eine Mine, explodiert sie\n" +
"und das Spiel ist zu Ende. Ist keine Mine auf dem Feld, dann enthüllt es\n" +
"die Anzahl an Minen, die diesem Feld direkt benachbart sind (waagrecht,\n" +
"senkrecht und diagonal). Glauben Sie eine Mine lokalisiert zu haben, dann\n" +
"können Sie das entsprechende Feld mit der rechten Maustaste markieren.\n" +
"\n" +
"Das Spiel ist zu Ende, wenn eine Mine explodiert oder wenn alle Felder\n" +
"mit Minen markiert und alle anderen aufgedeckt sind.\n" +
"\n" +
"Am Ende entscheiden die Anzahl an markierten Minen und die benötigte\n" +
"Zeit, ob Sie in die Ruhmeshalle kommen oder nicht.";
CONST spielregelnGad = "Spielregeln";
CONST spielregelnTitel = "Mine: Die Spielregeln";
(*$ ELSE *)
CONST quitGad = "Quit";
CONST shareware =
" Mine © 1992 by\n" +
"\n" +
" Thomas Ansorge, Dinkelackerring 55, W-6730 Neustadt/Weinstraße,\n" +
" Germany, Europe\n" +
"\n" +
"\n" +
"Mine is freely distributable copyrighted software. You have permission to\n" +
"distribute Mine to anyone you want on a non-commercial base and as long as\n" +
"Mine is complete. All other rights remain at the author alone.\n" +
"\n" +
"You are not allowed to change any part of Mine except for the highscore\n" +
"lists (where you are supposed to...).\n" +
"\n" +
"I do not ask for money if you like Mine and can not be made liable for any\n" +
"damage Mine does to anyone or anything directly or indirectly. YOU USE\n" +
"MINE ON YOUR OWN RISK!";
CONST sharewareTitel = "Mine:";
CONST spielregeln =
"To play mine, you have to follow these simple rules:\n" +
"\n" +
"Your field is a n * n square with INTEGER (n * n / 6) hidden mines and\n" +
"all you have to do is to mark them with a nice flag so that nobody\n" +
"stumbles over them. The problem: As I said, they are hidden, so you\n" +
"don't see them. But there is help available: If you click with your\n" +
"left mouse button on a field that does not contain a mine, it will tell\n" +
"you the number of mines hidden in its direct neighbourhood. If you hit\n" +
"a mine with the left mouse button, the game is over. With your right\n" +
"mouse button you can mark any field with a flag or collect a flag from\n" +
"a field. You have as many flags as there are mines.\n" +
"\n" +
"The game is over if you hit a mine with your left mouse button or if\n" +
"there is no field without either a number or a flag in it left. Then\n" +
"the program has a look at the number of mines you marked with a flag\n" +
"and the time it took and then perhaps you enter the highscorelist.";
CONST spielregelnGad = "how to play Mine";
CONST spielregelnTitel = "Mine: The rules of the game:";
(*$ ENDIF *)
CONST sharewareGads = spielregelnGad + "|" + quitGad;
VAR flags : IDCMPFlagSet;
nummer: LONGINT;
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur Info *)
flags := IDCMPFlagSet {};
REPEAT
nummer := TextRequest (shareware, NIL, sharewareGads, sharewareTitel, reqLib,
flags, windowPtr);
CASE nummer OF
|1: nummer := TextRequest (spielregeln, NIL, quitGad, spielregelnTitel,
reqLib, flags, windowPtr);
|0: (* QUIT: nichts *);
END (* CASE nummer *);
UNTIL nummer = 0;
END Info (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE InitImages;
(* initialisiert die Images *)
(* alles ist global *)
BEGIN (* Prozedur InitImages *)
WITH bombeImage DO
leftEdge :=0;
topEdge :=0;
width := boxX;
height := boxY;
depth := 2;
imageData := ADR (Images.BombePlane);
planePick := 3;
planeOnOff := 0;
nextImage := NIL;
END (* WITH bombeImage *);
WITH clickedImage DO
leftEdge :=0;
topEdge :=0;
width := boxX;
height := boxY;
depth := 2;
imageData := ADR (Images.ClickedPlane);
planePick := 3;
planeOnOff := 0;
nextImage := NIL;
END (* WITH clickedImage *);
WITH clickmeImage DO
leftEdge :=0;
topEdge :=0;
width := boxX;
height := boxY;
depth := 2;
imageData := ADR (Images.ClickMePlane);
planePick := 3;
planeOnOff := 0;
nextImage := NIL;
END (* WITH clickmeImage *);
WITH explosionImage DO
leftEdge :=0;
topEdge :=0;
width := boxX;
height := boxY;
depth := 2;
imageData := ADR (Images.ExplosionPlane);
planePick := 3;
planeOnOff := 0;
nextImage := NIL;
END (* WITH explosionImage *);
WITH fahneImage DO
leftEdge :=0;
topEdge := 0;
width := boxX;
height := boxY;
depth := 2;
imageData := ADR (Images.FahnePlane);
planePick := 3;
planeOnOff := 0;
nextImage := NIL;
END (* WITH fahneImage *);
WITH fahneORImage DO
leftEdge :=0;
topEdge := 0;
width := 12;
height := 8;
depth := 2;
imageData := ADR (Images.FahneORPlane);
planePick := 3;
planeOnOff := 0;
nextImage := NIL;
END (* WITH fahneImage *);
END InitImages (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE LadeRuhmeshalle (VAR ruhmeshalle: Ruhmeshalle;
ruhmeshalleName: ARRAY OF CHAR);
(* lädt bzw initialisiert mit 0 die Variable ruhmeshalle *)
VAR file: File;
i : [1..10];
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur LadeRuhmeshalle *)
Lookup (file, ruhmeshalleName, SIZE (ruhmeshalle), FALSE);
IF file.res = done THEN
ReadByteBlock (file, ruhmeshalle);
Close (file);
ELSE (* IF file.res *);
FOR i := 1 TO 10 DO
WITH ruhmeshalle [i] DO
anzM := 0;
WITH zeit DO
min := 99;
sec := 59;
END (* WITH zeit *);
name := "";
END (* WITH ruhmeshalle [i] *);
END (* FOR i *);
END (* IF file.res *);
END LadeRuhmeshalle (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE MaxAnzahlFelder (screenPtr: ScreenPtr): LONGINT;
(* stellt fest, wie groß das auf dem Screen screenPtr gezeichnete Feld maximal *)
(* sein kann, damit das ganze Fenster draufpaßt *)
VAR horiz, vert: LONGINT;
(* ---------------------------------------------------------------------------- *)
BEGIN (* Funktion MaxAnzahlFelder *)
horiz := (screenPtr^.width - 2 * 3 - 2 * 4) DIV (boxX + 1);
vert := (screenPtr^.height - 3 * randBreite - 8 -
LONGINT (screenPtr^.font^.ySize + CARDINAL (screenPtr^.wBorTop) + 1)) DIV boxY;
IF horiz <= vert THEN
RETURN horiz;
ELSE
RETURN vert;
END (* IF horiz *);
END MaxAnzahlFelder (* Funktion *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE Pos (ruhmeshalle: Ruhmeshalle;
eintrag : RuhmeshalleEintrag (* ohne name *)
): LONGINT;
(* stellt den Platz des neuen eintrags in der Ruhmeshalle fest *)
VAR pos: LONGINT;
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur Pos *)
pos := 1;
WHILE (eintrag.anzM < ruhmeshalle [pos].anzM) AND (pos < 10) DO
INC (pos);
END (* WHILE *);
IF (pos = 10) AND (eintrag.anzM < ruhmeshalle [pos].anzM) THEN
RETURN 11;
END (* IF (pos *);
IF eintrag.anzM > ruhmeshalle [pos].anzM THEN
RETURN pos;
END (* IF eintrag.anzM *);
WHILE (eintrag.zeit.min > ruhmeshalle [pos].zeit.min) AND (pos < 10) AND
(eintrag.anzM = ruhmeshalle [pos].anzM) DO
INC (pos);
END (* WHILE *);
IF (pos = 10) AND (eintrag.zeit.min > ruhmeshalle [pos].zeit.min) THEN
RETURN 11;
END (* IF (pos *);
IF eintrag.zeit.min < ruhmeshalle [pos].zeit.min THEN
RETURN pos;
END (* IF eintrag.zeit.min *);
WHILE (eintrag.zeit.sec >= ruhmeshalle [pos].zeit.sec) AND (pos < 10) AND
(eintrag.anzM = ruhmeshalle [pos].anzM) AND
(eintrag.zeit.min = ruhmeshalle [pos].zeit.min) DO
INC (pos);
END (* WHILE *);
IF (pos = 10) AND (eintrag.zeit.sec >= ruhmeshalle [pos].zeit.sec) THEN
RETURN 11;
END (* IF (pos *);
RETURN pos;
END Pos (* Funktion *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE SaveRuhmeshalle (ruhmeshalle : Ruhmeshalle;
ruhmeshalleName: ARRAY OF CHAR);
(* speichert die Ruhmeshalle *)
VAR file: File;
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur SaveRuhmeshalle *)
Lookup (file, ruhmeshalleName, SIZE (ruhmeshalle), TRUE);
WriteByteBlock (file, ruhmeshalle);
Close (file);
END SaveRuhmeshalle (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE VerteileMinen (VAR spielfeld: Spielfeld;
spielfeldMax : LONGINT;
anzMinen : LONGINT);
(* initialisiert das Spielfeld *)
VAR i, j, k: LONGINT;
(* ---------------------------------------------------------------------------- *)
BEGIN (* Prozedur VerteileMinen *)
(* Feld löschen <=> mit 0 füllen *)
FOR i := 1 TO spielfeldMax DO
FOR j := 1 TO spielfeldMax DO
spielfeld [i, j] := 0;
END (* FOR j *);
END (* FOR i *);
(* Minen nach Zufallsprinzip verteilen und Felder drumherum aktualisieren *)
k := 0;
REPEAT
i := RND (spielfeldMax) + 1;
j := RND (spielfeldMax) + 1;
IF spielfeld [i, j] # mine THEN
(* eine neue Mine *)
spielfeld [i, j] := mine;
INC (k);
IF i # 1 THEN
IF j # 1 THEN
IF spielfeld [i - 1, j - 1] # mine THEN
INC (spielfeld [i - 1, j - 1]); (* links oben *)
END;
END;
IF spielfeld [i - 1, j] # mine THEN
INC (spielfeld [i - 1, j]); (* oben *)
END;
IF j # spielfeldMax THEN
IF spielfeld [i - 1, j + 1] # mine THEN
INC (spielfeld [i - 1, j + 1]); (* rechts oben *)
END;
END;
END (* IF i # 1 *);
IF j # 1 THEN
IF spielfeld [i, j - 1] # mine THEN
INC (spielfeld [i, j - 1]); (* links *)
END;
END;
IF j # spielfeldMax THEN
IF spielfeld [i, j + 1] # mine THEN
INC (spielfeld [i, j + 1]); (* rechts *)
END;
END;
IF i # spielfeldMax THEN
IF j # 1 THEN
IF spielfeld [i + 1, j - 1] # mine THEN
INC (spielfeld [i + 1, j - 1]); (* links unten *)
END;
END;
IF spielfeld [i + 1, j] # mine THEN
INC (spielfeld [i + 1, j]); (* unten *)
END;
IF j # spielfeldMax THEN
IF spielfeld [i + 1, j + 1] # mine THEN
INC (spielfeld [i + 1, j + 1]); (* rechts unten *)
END;
END;
END (* IF i # spielfeldMax *);
END (* IF spielfeld [i, j] # mine *);
UNTIL k = anzMinen;
END VerteileMinen (* Prozedur *);
(* ------------------------------------------------------------------------------- *)
PROCEDURE Ziffer (ziffer: SHORTINT): CHAR;
(* Anzahl der Minen um ein Feld *)
BEGIN (* Funktion Ziffer *)
CASE ziffer OF
|0: RETURN "0";
|1: RETURN "1";
|2: RETURN "2";
|3: RETURN "3";
|4: RETURN "4";
|5: RETURN "5";
|6: RETURN "6";
|7: RETURN "7";
|8: RETURN "8";
END (* CASE ziffer *);
END Ziffer (* Funktion *);
(* ------------------------------------------------------------------------------- *)
(* ------------------------------------------------------------------------------- *)
BEGIN (* MODULE Mine *)
(* okay, was genau brauchen wir: *)
Assert (diskfontVersion >= 33, ADR ("DiskFont Library Version 33 Minimum!"));
Assert (dosVersion >= 33, ADR ("Dos Library Version 33 Minimum!"));
Assert (execVersion >= 33, ADR ("Exec Library Version 33 Minimum!"));
Assert (gadtoolsVersion >= 36, ADR ("GadTools Library Version 36 Minimum!"));
Assert (graphicsVersion >= 33, ADR ("Graphics Library Version 33 Minimum!"));
Assert (intuitionVersion >= 36, ADR ("Intuition Library Version 36 Minimum!"));
IF reqtoolsBase # NIL THEN
reqLib := reqtools;
ELSE (* IF reqtoolsBase *)
IF reqBase # NIL THEN
reqLib := req;
ELSE (* IF reqBase *)
reqLib := system;
END (* IF reqBase *);
END (* IF reqtoolsBase *);
WITH intuiText DO
frontPen := schwarz;
backPen := grau;
drawMode := jam2;
iTextFont := ADR (fontAttr);
nextText := NIL;
END (* WITH intuiText *);
screenPtr := NIL;
windowPtr := NIL;
windowPtr2 := NIL;
visualInfo := NIL;
DateStamp (ADR (date));
PutSeed (Eor (date.days, Eor (date.minute, date.tick)));
(* mein Font *)
WITH fontAttr DO
name := ADR (fontName);
ySize := fontHoehe;
style := FontStyleSet {};
flags := FontFlagSet {};
END (* WITH fontAttr *);
fontPtr := OpenDiskFont (ADR (fontAttr));
spielfeldMax := 10;
screenPtr := LockPubScreen (NIL);
LOOP
ende := FALSE;
anzNummer := 0;
WITH zeit DO
ticks := 0;
minuten := 0;
sekunden := 0;
WITH zeitIText DO
frontPen := schwarz;
backPen := grau;
drawMode := jam2;
leftEdge := 0;
topEdge := -1;
iTextFont := ADR (fontAttr);
iText := ADR (zeitStr);
nextText := NIL;
END (* WITH zeitIText *);
END (* WITH Zeit *);
(* das Anfangs-Fenster *)
spielFeldMax := MaxAnzahlFelder (screenPtr);
IF spielFeldMax > 77 THEN
spielFeldMax := 77;
END (* IF spielFeldMax *);
innerWidth := 180;
windowPtr := OpenWindowTagList (NIL, TAG (tagList,
waInnerHeight, 90,
waInnerWidth , innerWidth,
waLeft , (LONGINT (screenPtr^.width) - 204) DIV 2,
waTop , (LONGINT (screenPtr^.height) - 70) DIV 2,
waTitle , ADR (mineStr),
waFlags , CAST (LONGINT, WindowFlagSet {windowDrag,
windowClose,
gimmeZeroZero,
reportMouse,
activate,
windowDepth}),
waIDCMP , CAST (LONGINT, IDCMPFlagSet {closeWindow,
refreshWindow} +
buttonIDCMP +
sliderIDCMP),
waPubScreen , screenPtr,
tagEnd , 0));
Assert (windowPtr # NIL, ADR (openWindowError));
Assert (windowPtr^.userPort # NIL, ADR (userPortError));
IF visualInfo = NIL THEN
visualInfo := GetVisualInfoA (windowPtr^.wScreen, NIL);
END (* IF visualInfo *);
gList := NIL;
contextPtr := CreateContext (gList); (* bereitet gList für GadTools vor *)
(* contextPtr und gList zeigen jetzt auf den selben Speicherbereich *)
string80 := "5 ";
ValToStr (spielFeldMax, FALSE, string2, 10, 2, "0", err);
Concat (string80, string2);
IF gList # NIL THEN
(* der Slider *)
WITH newGadget DO
width := 154;
height := 12;
leftEdge := (innerWidth - width) DIV 2;
topEdge := 18;
gadgetText := ADR (string80);
textAttr := ADR (fontAttr);
gadgetID := sliderGadID;
flags := NewGadgetFlagSet {placetextBelow};
userData := NIL;
END (* WITH newGadget *);
sliderZahlPos := (innerWidth - 160) DIV 2 + 104;
newGadget.visualInfo := visualInfo;
gadgetPtr := CreateGadgetA (sliderKind, gList^, newGadget, TAG (tagList,
gtslMin , 5,
gtslMax , spielFeldMax,
gtslLevel , spielfeldMax,
gtslMaxLevelLen, 21,
gaRelVerify , TRUE,
gaImmediate , TRUE,
tagEnd , 0));
(* weiter *)
WITH newGadget DO
width := 80;
height := 12;
leftEdge := (innerWidth - width) DIV 2;
topEdge := 45;
gadgetText := ADR (weiter);
textAttr := ADR (fontAttr);
gadgetID := weiterGadID;
flags := NewGadgetFlagSet {placetextIn};
userData := NIL;
END (* WITH newGadget *);
newGadget.visualInfo := visualInfo;
gadgetPtr := CreateGadgetA (buttonKind, gadgetPtr^, newGadget, NIL);
(* Infos und Hilfe *)
WITH newGadget DO
width := 128;
height := 12;
leftEdge := (innerWidth - width) DIV 2;
topEdge := 60;
gadgetText := ADR (info);
textAttr := ADR (fontAttr);
gadgetID := infoGadID;
flags := NewGadgetFlagSet {placetextIn};
userData := NIL;
END (* WITH newGadget *);
newGadget.visualInfo := visualInfo;
gadgetPtr := CreateGadgetA (buttonKind, gadgetPtr^, newGadget, NIL);
(* Ruhmeshalle ansehen *)
WITH newGadget DO
width := 160;
height := 12;
leftEdge := (innerWidth - width) DIV 2;
topEdge := 75;
gadgetText := ADR (ruhmeshalleGadgetName);
textAttr :=ADR (fontAttr);
gadgetID := ruhmGadID;
flags := NewGadgetFlagSet {placetextIn};
userData := NIL;
END (* WITH newGadget *);
newGadget.visualInfo := visualInfo;
gadgetPtr := CreateGadgetA (buttonKind, gadgetPtr^, newGadget, NIL);
i := AddGList (windowPtr, gList, 0, -1, NIL);
RefreshGadgets (gList, windowPtr, NIL);
GTRefreshWindow (windowPtr, NIL); (* für GadTools *)
END (* IF gList *);
i := 0;
(* "Seitenlänge" über Prop-Gadget schreiben *)
intuiText.leftEdge := 17;
intuiText.topEdge := 0;
intuiText.iText := ADR (string80);
string80 := seitenlaenge;
PrintIText (windowPtr^.rPort, ADR (intuiText), sliderZahlPos - 104, 7);
intuiText.iText := ADR (string2);
ValToStr (spielfeldMax, FALSE, string2, 10, 2, " ", err);
PrintIText (windowPtr^.rPort, ADR (intuiText), sliderZahlPos, 7);
REPEAT
nachricht := GTGetIMsg (windowPtr^.userPort);
IF nachricht = NIL THEN
WaitPort (windowPtr^.userPort);
nachricht := GTGetIMsg (windowPtr^.userPort);
END (* IF nachricht *);
IF nachricht # NIL THEN
flags := nachricht^.class;
gadgetPtr := nachricht^.iAddress;
code := nachricht^.code; (* nur bei GadTools UND GTGetIMsg *)
GTReplyIMsg (nachricht);
IF closeWindow IN flags THEN
EXIT (* LOOP *);
ELSIF refreshWindow IN flags THEN
GTBeginRefresh (windowPtr);
GTEndRefresh (windowPtr, TRUE);
ELSIF gadgetUp IN flags THEN
IF gadgetPtr # NIL THEN
i := gadgetPtr^.gadgetID;
IF i = infoGadID THEN
Info (windowPtr);
END (* IF i *);
IF i = ruhmGadID THEN
ValToStr (spielfeldMax, FALSE, string2, 10, 2, " ", err);
Copy (string30, ruhmeshalleName);
Concat (string30, string2);
LadeRuhmeshalle (ruhmeshalle, string30);
innerWidth := 276;
innerHeight := 124;
Copy (string30, ruhmeshalleFensterName);
Concat (string30, string2);
windowPtr2 := OpenWindowTagList (NIL, TAG (tagList,
waTitle , ADR (string30),
waInnerWidth , innerWidth,
waInnerHeight, innerHeight,
waLeft , (screenPtr^.width - innerWidth) DIV 2,
waTop , (screenPtr^.height - innerHeight) DIV 2,
waFlags , CAST (LONGINT, WindowFlagSet {windowClose,
activate,
windowDrag,
windowDepth,
gimmeZeroZero}),
waIDCMP , CAST (LONGINT, IDCMPFlagSet {closeWindow,
refreshWindow,
mouseButtons}),
tagEnd , 0));
Assert (windowPtr2 # NIL, ADR (openWindowError));
Assert (windowPtr2^.userPort # NIL, ADR (userPortError));
(* windowPtr^ und WindowPtr2^ sind auf dem selben Screen, also *)
(* darf ich auch das selbe visualInfo verwenden *)
DrawBevelBoxA (windowPtr2^.rPort, 20, 7, 234, 108, TAG (tagList,
gtbbRecessed, 0,
gtVisualInfo, visualInfo,
tagEnd , 0));
WITH intuiText DO
leftEdge := 0;
topEdge := 12;
END (* WITH intuiText *);
FOR j := 1 TO 10 DO
IF ruhmeshalle [j].anzM = AnzMinen (spielfeldMax) THEN
intuiText.frontPen := blau;
END (* IF ruhmeshalle *);
intuiText.iText := ADR (ruhmeshalle [j].name);
PrintIText (windowPtr2^.rPort, ADR (intuiText), 34,
10 * (j - 1));
intuiText.frontPen := schwarz;
END (* FOR j *);
flags := IDCMPFlagSet {};
REPEAT
nachricht := GetMsg (windowPtr2^.userPort);
IF nachricht = NIL THEN
WaitPort (windowPtr2^.userPort);
nachricht := GetMsg (windowPtr2^.userPort);
END (* IF nachricht *);
IF nachricht # NIL THEN
flags := nachricht^.class;
ReplyMsg (nachricht);
END (* IF nachricht *);
IF refreshWindow IN flags THEN
BeginRefresh (windowPtr2);
EndRefresh (windowPtr2, TRUE);
END (* IF refreshWindow *);
IF closeWindow IN flags THEN
EXIT (* LOOP *);
END (* IF closeWindows *);
UNTIL mouseButtons IN flags;
CloseWindow (windowPtr2);
windowPtr2 := NIL;
END (* IF i *);
END (* IF gadgetPtr # NIL *);
ELSIF gadgetDown IN flags THEN
IF gadgetPtr # NIL THEN
IF gadgetPtr^.gadgetID = sliderGadID THEN
REPEAT
nachricht := GTGetIMsg (windowPtr^.userPort);
IF nachricht = NIL THEN
WaitPort (windowPtr^.userPort);
nachricht := GTGetIMsg (windowPtr^.userPort);
END (* IF nachricht *);
IF nachricht # NIL THEN
flags := nachricht^.class;
code := nachricht^.code;
GTReplyIMsg (nachricht);
IF (mouseMove IN flags) OR (gadgetUp IN flags) THEN
(* jemand bewegt den Slider *)
spielfeldMax := LONGINT (code);
intuiText.leftEdge := 17;
intuiText.topEdge := 0;
intuiText.iText := ADR (string2);
ValToStr (spielfeldMax, FALSE, string2, 10, 2, " ", err);
PrintIText (windowPtr^.rPort, ADR (intuiText),
sliderZahlPos, 7);
END (* IF mouseMove *);
END (* IF nachricht *);
UNTIL gadgetUp IN flags; (* losgelassen *)
END (* IF gadgetPtr^. *);
END (* IF gadgetPtr *);
END (* IF closeWindow *);
END (* IF nachricht *);
UNTIL i = weiterGadID;
FreeVisualInfo (visualInfo);
visualInfo := NIL;
i := RemoveGList (windowPtr, gList, 5);
FreeGadgets (gList);
gList := NIL;
CloseWindow (windowPtr);
windowPtr := NIL;
anzMinen := AnzMinen (spielfeldMax);
(* spielfeldMax <= 44 (PAL SuperHires-Interlace mit vollem Overscan) *)
(* ==> anzMinen <= 322 *)
(* spielfeldMax <= 77 <==> anzMinen dreistellig *)
anzFahnen := 0;
(* Das eigentliche Spiel-Fenster *)
string2 := "";
VerteileMinen (spielfeld, spielfeldMax, anzMinen);
innerWidth := LONGINT ((spielfeldMax * boxX) + (4 * randBreite) + spielfeldMax -
1);
innerHeight := LONGINT ((spielfeldMax * boxY) + (2 * randBreite) - 2 + 10);
windowPtr := OpenWindowTagList (NIL, TAG (tagList,
waTitle , ADR (mineStr),
waInnerWidth , innerWidth,
waInnerHeight, innerHeight,
waFlags , CAST (LONGINT, WindowFlagSet {windowDrag, windowDepth,
windowClose, activate, gimmeZeroZero, rmbTrap}),
waIDCMP , CAST (LONGINT, IDCMPFlagSet {mouseButtons, closeWindow,
refreshWindow, intuiTicks}),
waLeft , (screenPtr^.width - innerWidth) DIV 2,
waTop , (screenPtr^.height - innerHeight) DIV 2,
waPubScreen , screenPtr,
tagEnd , 0));
Assert (windowPtr # NIL, ADR (openWindowError));
Assert (windowPtr^.userPort # NIL, ADR (userPortError));
InitImages ();
IF spielfeldMax < 8 THEN
zeit.zeitIText.leftEdge := (windowPtr^.gzzWidth - 88) DIV 2;
ELSE (* IF spielfeldMax *)
zeit.zeitIText.leftEdge := (((windowPtr^.gzzWidth DIV 2) - 88 + randBreite)
DIV 2) + randBreite;
intuiText.topEdge := -1;
(* leftEdge: rechts der Mitte, alles 44 Pixel breit, davon FahneORImage 12 *)
intuiText.leftEdge := (windowPtr^.gzzWidth DIV 2) +
(((windowPtr^.gzzWidth DIV 2) - 44 - randBreite) DIV 2) + 12;
intuiText.iText := ADR (string30);
END (* IF spielfeldMax *);
(* Felder zeichnen *)
FOR i := 1 TO spielfeldMax DO (* Zeilen *)
FOR j := 1 TO spielfeldMax DO (* Spalten *)
DrawImage (windowPtr^.rPort, ADR (clickmeImage),
2 * randBreite + (j - 1) * clickmeImage.width + horoffset * (j - 1),
randBreite + (i - 1) * clickmeImage.height);
END (* FOR j *);
END (* FOR i *);
Copy (zeit.zeitStr, zeitS);
Concat (zeit.zeitStr, "00:00");
PrintIText (windowPtr^.rPort, ADR (zeit.zeitIText), 0,
2 * randBreite + spielfeldMax * boxY);
IF spielfeldMax >= 8 THEN
DrawImage (windowPtr^.rPort, ADR (fahneORImage),
((windowPtr^.gzzWidth DIV 2) + ((windowPtr^.gzzWidth DIV 2) - 44) DIV 2) - 1,
2 * randBreite + spielfeldMax * boxY - 1);
ValToStr (anzMinen - anzFahnen, FALSE, string30, 10, 3, " ", err);
Insert (string30, 0, ":\o");
PrintIText (windowPtr^.rPort, ADR (intuiText), 0,
2 * randBreite + spielfeldMax * boxY);
END (* IF spielfeldMax *);
(* Aktion des Spielers abwarten und reagieren *)
flags := IDCMPFlagSet {};
REPEAT
nachricht := GetMsg (windowPtr^.userPort);
IF nachricht = NIL THEN
WaitPort (windowPtr^.userPort);
nachricht := GetMsg (windowPtr^.userPort);
END (* IF nachricht *);
IF nachricht # NIL THEN
flags := nachricht^.class;
qualifiers := nachricht^.qualifier;
mausX := windowPtr^.gzzMouseX;
mausY := windowPtr^.gzzMouseY;
ReplyMsg (nachricht);
(* so, jetzt geht's ans Auswerten *)
IF intuiTicks IN flags THEN
IF zeit.ticks < 9 THEN
INC (zeit.ticks);
ELSE (* IF zeit.ticks = 9 *)
zeit.ticks := 0;
IF zeit.sekunden < 59 THEN
INC (zeit.sekunden);
ELSE (* IF zeit.sekunden *)
zeit.sekunden := 0;
IF zeit.minuten < 99 THEN
INC (zeit.minuten);
ELSE (* IF zeit.minuten *)
ende := TRUE;
END (* IF zeit.minuten *);
END (* IF zeit.sekunden *);
IF NOT ende THEN
WITH zeit DO
Copy (zeitStr, zeitS);
ValToStr (minuten, FALSE, hilfeStr, 10, 2, "0", err);
Concat (zeitStr, hilfeStr);
ConcatChar (zeitStr, ":");
ValToStr (sekunden, FALSE, hilfeStr, 10, 2, "0", err);
Concat (zeitStr, hilfeStr);
PrintIText (windowPtr^.rPort, ADR (zeitIText), 0,
2 * randBreite + spielfeldMax * boxY);
END (* WITH Zeit *);
END (* IF NOT ende *);
END (* IF zeit.ticks *);
END (* IF intuiTicks *);
IF refreshWindow IN flags THEN
BeginRefresh (windowPtr);
EndRefresh (windowPtr, TRUE);
END (* IF refreshWindow *);
IF mouseButtons IN flags THEN
i := ((mausY - randBreite) DIV boxY) + 1; (* Zeile *)
j := ((mausX - 2 * randBreite) DIV (boxX + horoffset)) + 1;
IF (i >= 1) AND (i <= spielfeldMax) AND (j >= 1) AND
(j <= spielfeldMax) THEN
(* das Feld [i, j] angeklickt *)
IF rightButton IN qualifiers THEN
IF spielfeld [i, j] >= mine THEN
IF anzFahnen < anzMinen THEN
DrawImage (windowPtr^.rPort, ADR (fahneImage),
2 * randBreite + (j - 1) * fahneImage.width +
horoffset * (j - 1),
randBreite + (i - 1) * fahneImage.height);
spielfeld [i, j] := spielfeld [i, j] + fahne;
INC (anzFahnen);
END (* IF anzFahnen *);
ELSE (* IF spielfeld [i, j] >= mine *)
IF spielfeld [i, j] <= fahne + 8 THEN
DrawImage (windowPtr^.rPort, ADR (clickmeImage),
2 * randBreite + (j - 1) * clickmeImage.width +
horoffset * (j - 1),
randBreite + (i - 1) * clickmeImage.height);
spielfeld [i, j] := spielfeld [i, j] - fahne;
DEC (anzFahnen);
END (* IF spielfeld [i, j] = fahne *);
END (* IF spielfeld [i, j] >= mine *);
IF spielfeldMax >= 8 THEN
ValToStr (anzMinen - anzFahnen, FALSE, string30, 10, 3, " ",
err);
Insert (string30, 0, ":\o");
PrintIText (windowPtr^.rPort, ADR (intuiText), 0,
2 * randBreite + spielfeldMax * boxY);
END (* IF spielfeldMax *);
ELSIF leftButton IN qualifiers THEN
IF spielfeld [i, j] >= mine THEN
IF spielfeld [i, j] # mine THEN
ModifyIDCMP (windowPtr, IDCMPFlagSet {});
DrawClickedImage (windowPtr, spielfeld, spielfeldMax, i, j,
anzNummer);
ModifyIDCMP (windowPtr,
IDCMPFlagSet {mouseButtons, closeWindow, refreshWindow,
intuiTicks});
ELSE (* IF # mine *)
DrawImage (windowPtr^.rPort, ADR (explosionImage),
2 * randBreite + (j - 1) * explosionImage.width +
horoffset * (j - 1),
randBreite + (i - 1) * explosionImage.height);
Beep (booob, infoPri);
ende := TRUE;
END (* IF # mine *);
END (*IF >= mine *);
END (* IF rightButton *);
END (* IF (i >= 1 *);
END (* IF mouseButtons *);
END (* IF nachricht # NIL *);
UNTIL ende OR (closeWindow IN flags) OR
((spielfeldMax * spielfeldMax - anzFahnen - anzNummer) = 0);
IF closeWindow IN flags THEN
CloseWindow (windowPtr);
windowPtr := NIL;
EXIT (* LOOP *);
END (* IF closeWindow *);
ModifyIDCMP (windowPtr, IDCMPFlagSet {}); (* keine Nachrichten mehr! *)
(* Anzahl der gefundenen Minen zählen *)
anzMinen := 0;
FOR i := 1 TO spielfeldMax DO
FOR j := 1 TO spielfeldMax DO
IF spielfeld [i, j] = fahne + mine THEN
INC (anzMinen);
(* Bombe zeichnen *)
DrawImage (windowPtr^.rPort, ADR (bombeImage),
2 * randBreite + (j - 1) * clickedImage.width + horoffset * (j - 1),
randBreite + (i - 1) * clickedImage.height);
END (* IF spielfeld *);
END (* FOR j *);
END (* FOR i *);
IF ((spielfeldMax * spielfeldMax) - anzNummer - anzMinen) = 0 THEN
(* alles abgeräumt! *)
Beep (beeeb, infoPri);
END (* IF ((spielfeldMax *);
ValToStr (spielfeldMax, FALSE, string2, 10, 2, " ", err);
Copy (string30, ruhmeshalleName);
Concat (string30, string2);
LadeRuhmeshalle (ruhmeshalle, string30);
eintrag.anzM := anzMinen;
eintrag.zeit.min := zeit.minuten;
eintrag.zeit.sec := zeit.sekunden;
pos := Pos (ruhmeshalle, eintrag);
IF (pos <= 10) AND (reqLib # system) THEN (* drin -- String-Requester! *)
j := StringRequest (eintrag.name, 17, 16, stringReqTitle, windowPtr,
reqLib);
IF j = noError THEN
FuegeEintragEin (ruhmeshalle, eintrag, pos);
SaveRuhmeshalle (ruhmeshalle, string30);
END (* IF noError *);
ELSE (* IF pos *)
(* nicht in der Ruhmeshalle -- auf Mausklick warten *)
ModifyIDCMP (windowPtr, IDCMPFlagSet {mouseButtons, closeWindow});
REPEAT
nachricht := GetMsg (windowPtr^.userPort);
IF nachricht = NIL THEN
WaitPort (windowPtr^.userPort);
nachricht := GetMsg (windowPtr^.userPort);
END (* IF nachricht *);
flags := nachricht^.class;
ReplyMsg (nachricht);
IF closeWindow IN flags THEN
EXIT (* LOOP *);
END (* IF closeWindow *);
UNTIL mouseButtons IN flags;
END (* IF pos *);
CloseWindow (windowPtr);
windowPtr := NIL;
(* Ruhmeshalle anzeigen *);
Copy (string80, ruhmeshalleFensterName);
Concat (string80, string2);
innerWidth := 276;
innerHeight := 124;
windowPtr := OpenWindowTagList (NIL, TAG (tagList,
waTitle , ADR (string80),
waInnerWidth , innerWidth,
waInnerHeight, innerHeight,
waLeft , (screenPtr^.width - innerWidth) DIV 2,
waTop , (screenPtr^.height - innerHeight) DIV 2,
waFlags , CAST (LONGINT, WindowFlagSet {windowClose,
windowDrag,
activate,
windowDepth,
gimmeZeroZero}),
waIDCMP , CAST (LONGINT, IDCMPFlagSet {closeWindow, refreshWindow,
mouseButtons}),
tagEnd , 0));
Assert (windowPtr # NIL, ADR (openWindowError));
Assert (windowPtr^.userPort # NIL, ADR (userPortError));
IF visualInfo = NIL THEN
visualInfo := GetVisualInfoA (windowPtr^.wScreen, NIL);
END (* IF visualInfo *);
DrawBevelBoxA (windowPtr^.rPort, 20, 7, 234, 108, TAG (tagList,
gtbbRecessed, 0,
gtVisualInfo, visualInfo,
tagEnd , 0));
FreeVisualInfo (visualInfo);
visualInfo := NIL;
WITH intuiText DO
leftEdge := 0;
topEdge := 12;
END (* WITH intuiText *);
FOR i := 1 TO 10 DO
intuiText.iText := ADR (ruhmeshalle [i].name);
IF ruhmeshalle [i].anzM = AnzMinen (spielfeldMax) THEN
intuiText.frontPen := blau;
END (* IF ruhmeshalle *);
IF (i = pos) AND (j = noError) THEN
intuiText.frontPen := weiss;
END (* IF i *);
PrintIText (windowPtr^.rPort, ADR (intuiText), 34, 10 * (i - 1));
intuiText.frontPen := schwarz;
END (* FOR i *);
flags := IDCMPFlagSet {};
REPEAT
nachricht := GetMsg (windowPtr^.userPort);
IF nachricht = NIL THEN
WaitPort (windowPtr^.userPort);
nachricht := GetMsg (windowPtr^.userPort);
END (* IF nachricht *);
IF nachricht # NIL THEN
flags := nachricht^.class;
ReplyMsg (nachricht);
END (* IF nachricht *);
IF refreshWindow IN flags THEN
BeginRefresh (windowPtr);
EndRefresh (windowPtr, TRUE);
END (* IF refreshWindow *);
IF closeWindow IN flags THEN
EXIT (* LOOP *);
END (* IF closeWindow *);
UNTIL mouseButtons IN flags;
CloseWindow (windowPtr);
windowPtr := NIL;
END (* LOOP *);
(* ------------------------------------------------------------------------------- *)
CLOSE;
IF screenPtr # NIL THEN
UnlockPubScreen (NIL, screenPtr);
screenPtr := NIL;
END (* IF screenPtr *);
IF visualInfo # NIL THEN
FreeVisualInfo (visualInfo);
visualInfo := NIL;
END (* IF visualInfo *);
IF windowPtr # NIL THEN
IF gList # NIL THEN
i := RemoveGList (windowPtr, gList, 5);
FreeGadgets (gList);
gList := NIL;
END (* IF gList *);
CloseWindow (windowPtr);
windowPtr := NIL;
END (* IF windowPtr *);
IF windowPtr2 # NIL THEN
CloseWindow (windowPtr2);
windowPtr2 := NIL;
END (* IF windowPtr2 *);
IF fontPtr # NIL THEN
CloseFont (fontPtr);
fontPtr := NIL;
END (* IF fontPtr *);
END Mine (* MODUL *).